/*
 * TMap Designer - A Thematic Map design software
 * Copyright (C) 2006 World Health Organization
 * http://www.who.int
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
package who.tmap.ui;
 
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyVetoException;
import java.io.File;

import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.Copies;
import javax.print.attribute.standard.JobName;
import javax.swing.BoxLayout;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JDesktopPane;
import javax.swing.JInternalFrame;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent;

import org.apache.log4j.Logger;
import org.bushe.swing.event.EventBus;

import who.tmap.bo.Annotations;
import who.tmap.bo.Attrs;
import who.tmap.bo.ThematicMap;
import who.tmap.bo.cd.CDTypes;
import who.tmap.bo.cd.CartographicDisplay;
import who.tmap.bo.impl.BizObjectFactory;
import who.tmap.common.TMapException;
import who.tmap.toolkit.EditMode;
import who.tmap.toolkit.MappingToolKit;
import who.tmap.toolkit.impl.PolygonNamesToAttrsHelper;
import who.tmap.ui.cd.JFrameCartographicDisplay;
import who.tmap.ui.event.DataStructureHasChanged;
import who.tmap.ui.util.AnnotationsUIHelper;
import who.tmap.ui.util.CartographicDisplayUIHelper;
import who.tmap.ui.util.CursorHelper;
import who.tmap.ui.util.DataTableDataModel;
import who.tmap.ui.util.DataUIHelper;
import who.tmap.ui.util.MapUIHelper;
import who.tmap.ui.util.MiscUIHelper;
import who.tmap.ui.util.ThematicMapTreeUIHelper;
import who.tmap.ui.util.ThematicMapUIHelper;

/**
 * @author stl
 *
 * This window is a MDI JInternalFrame
 * containing all the other windows
 * necessary to edit a thematic map 
 */
public class JFrameThematicMap extends JInternalFrame {
    
    private static Logger logger = Logger.getLogger(JFrameThematicMap.class);  
    
    private JFrameThematicMap thisFrame =this;
	
    private ThematicMapUIHelper thematicMapUIHelper =new ThematicMapUIHelper( this );
    private MapUIHelper baseMapUIHelper =new MapUIHelper();        
    private DataUIHelper dataUIHelper =new DataUIHelper();
    private CartographicDisplayUIHelper cdUIHelper =new CartographicDisplayUIHelper();  
    private AnnotationsUIHelper annUIHelper =new AnnotationsUIHelper();
    private MiscUIHelper miscUIHelper =new MiscUIHelper();	
    private CursorHelper cursorHelper =new CursorHelper();
    private ThematicMapTreeUIHelper treeHelper =new ThematicMapTreeUIHelper( this );
	
	private ThematicMap thematicMap;
	
	private int splitPaneDividerLocation;
	private int splitPaneDividerSize;

	private JFrameMain jFrameMain;
	public JFrameMap jFrameMap =new JFrameMap();
	public JFrameData jFrameData =new JFrameData();
	public JFrameCartographicDisplay jFrameCartographicDisplay;
	public JFrameAnnotations jFrameAnnotations =new JFrameAnnotations();	
	private JFrameWizard jFrameWizard =new JFrameWizard();
	
	private JPanel jContentPane = null;

	private JSplitPane jSplitPane = null;
	private JDesktopPane jDesktopPane = null;
	private JScrollPane jScrollPaneLeft = null;
	public JTree jTree = null;
	
	private Dimension previousSize =null;
	public boolean enableAutoResize =false;
	
	private JPopupMenu jPopupMenuThematicMap =null;
	private JPopupMenu jPopupMenuBaseMap =null;
	private JPopupMenu jPopupMenuData =null;
	private JPopupMenu jPopupMenuCartographicDisplay =null;	
	private JPopupMenu jPopupMenuAnnotations =null;			
	
	private JMenuItem jMenuItemCartographicDisplayNew = null;
	private JMenuItem jMenuItemThematicMapNew = null;
	private JMenuItem jMenuItemBaseMapNew = null;
	private JMenuItem jMenuItemBaseMapProject =null;
	private JMenuItem jMenuItemThematicMapOpen = null;
	private JMenuItem jMenuItemBaseMapOpen = null;
	private JMenuItem jMenuItemDataNew = null;
	private JMenuItem jMenuItemDataOpen = null;
	private JMenuItem jMenuItemAnnotationsNew = null;
	private JMenuItem jMenuItemBaseMapSave = null;
	private JMenuItem jMenuItemThematicMapSave = null;
	private JMenuItem jMenuItemThematicMapSaveAs = null;
	private JMenuItem jMenuItemBaseMapSaveAs = null;
	private JMenuItem jMenuItemDataSave = null;
	private JMenuItem jMenuItemDataSaveAs = null;
	private JMenuItem jMenuItemDataReload =null;
	private JMenuItem jMenuItemAnnotationsOpen = null;
	private JMenuItem jMenuItemAnnotationsSave = null;
	private JMenuItem jMenuItemAnnotationsSaveAs = null;
	private JMenuItem jMenuItemCartographicDisplayOpen = null;
	private JMenuItem jMenuItemCartographicDisplaySave = null;
	private JMenuItem jMenuItemCartographicDisplaySaveAs = null;
	private JMenuItem jMenuItemDataPrint = null;
	private JPanel jPanelLeft = null;
	private JPanel jPanelRight = null;
	
	private JMenuItem jMenuItemDataImport = null;
	private JMenuItem jMenuItemThematicMapPrint = null;
	private JMenuItem jMenuItemThematicMapClipboardCopy = null;
	private JMenuItem jMenuItemThematicMapWizard = null;
	private JMenuItem jMenuItemThematicMapFullScreen = null;

	private JCheckBoxMenuItem jCheckBoxMenuItemBaseMapEdit = null;
	private JCheckBoxMenuItem jCheckBoxMenuItemAnnotationsEdit = null;
	private JMenuItem jMenuItemThematicMapProperties = null;
	private JCheckBoxMenuItem jCheckBoxMenuItemDataEdit = null;

	private JMenuItem jMenuItemDataCreatePointEntryStructure = null;
	private JMenuItem jMenuItemDataCreateAndPopulateWithJoinId = null;

	private JMenuItem jMenuItemDataEditStructure = null;
	private JMenuItem jMenuItemCartographicDisplayEditNonMatchingInformation = null;

	/**
	 * This is the default constructor
	 */
	public JFrameThematicMap() {
		super( "Thematic Map", 
						  false, //resizable
						  false, //closable
						  false, //maximizable
						  false);//iconifiable
		initialize();
	}
	
	/**
	 * This method initializes this
	 * 
	 * @return void
	 */
	private void initialize() {
		try {
            thematicMap =(ThematicMap)BizObjectFactory.getInstance().get( BizObjectFactory.THEMATIC_MAP );
        } catch (TMapException e) {
            miscUIHelper.displayErrorMessage( this, e );
        }
        
		jFrameMap.getMappingToolKit().setThematicMap( thematicMap );
		jFrameCartographicDisplay =new JFrameCartographicDisplay( jFrameMap.getMappingToolKit(), jFrameMap.getMil() );
		jFrameMap.setFrameCartographicDisplay( jFrameCartographicDisplay );
		jFrameMap.setFrameData( jFrameData );
        
		setSize(600, 400);
		setContentPane(getJContentPane());

		setFocusable( true );
		
		thematicMapUIHelper.newThematicMap( getContentPane() );	
		
		resetEditMode();
	}
	
	public void resetEditMode() {
		setEditMode( EditMode.NONE );
		
		getJCheckBoxMenuItemBaseMapEdit().setSelected( false );
		getJCheckBoxMenuItemDataEdit().setSelected( false );
		getJCheckBoxMenuItemAnnotationsEdit().setSelected( false );
	}
	
	public int saveNeededUI() {
		logger.debug("saveNeededUI()");
		return thematicMapUIHelper.saveNeededUI( getContentPane(), thematicMap );
	}
		
	private JPanel getJContentPane() {
		if (jContentPane == null) {
			jContentPane = new JPanel();
			jContentPane.setLayout(new BorderLayout());
			jContentPane.add(getJSplitPane(), BorderLayout.CENTER);								

		}
		return jContentPane;
	}
	
	public JSplitPane getJSplitPane() {
		if(jSplitPane == null) {
			jSplitPane = new JSplitPane();
			jSplitPane.setRightComponent(getJPanelRight());
			jSplitPane.setLeftComponent(getJPanelLeft());
			jSplitPane.setOneTouchExpandable( true );
			
			jSplitPane.addPropertyChangeListener( 
					new PropertyChangeListener() {
						public void propertyChange(PropertyChangeEvent e) {
							if ( "dividerLocation".equals( e.getPropertyName() ) ) {
								int prevLocation = ((Integer)e.getOldValue()).intValue();
								int newLocation = ((Integer)e.getNewValue()).intValue();
								getJDesktopPane().setSize( getJDesktopPane().getWidth() - newLocation + prevLocation
														 , getJDesktopPane().getHeight() );
								rearrangeWindowsAfterResize();
							}
						}
					});
		}
		return jSplitPane;
	}
	
	public JDesktopPane getJDesktopPane() {
		if(jDesktopPane == null) {
			jDesktopPane =new JDesktopPane();

			jFrameData.setWizardMode( false );
			jFrameData.setThematicMap( thematicMap );
			jFrameCartographicDisplay.setWizardMode( false );
			jFrameCartographicDisplay.setThematicMap( thematicMap );
			
			jFrameAnnotations.setThematicMap( thematicMap );
			jFrameAnnotations.setMtk( jFrameMap.getMappingToolKit() );
			
			jFrameWizard.setJFrameThematicMap( this );
	
			jDesktopPane.add( jFrameMap );
			jDesktopPane.add( jFrameData );
			jDesktopPane.add( jFrameCartographicDisplay );
			jDesktopPane.add( jFrameAnnotations );	
			jDesktopPane.add( jFrameWizard );
			
			jFrameMap.addInternalFrameListener(new InternalFrameAdapter() {
				public void internalFrameActivated(InternalFrameEvent e) {
					treeHelper.updateJTreeSelection();
				}
			});				
			
			jFrameData.addInternalFrameListener(new InternalFrameAdapter() {
				public void internalFrameActivated(InternalFrameEvent e) {
					treeHelper.updateJTreeSelection();
				}
			});				
			
			jFrameCartographicDisplay.addInternalFrameListener(new InternalFrameAdapter() {
				public void internalFrameActivated(InternalFrameEvent e) {
					treeHelper.updateJTreeSelection();
				}
			});			
			
			jFrameAnnotations.addInternalFrameListener(new InternalFrameAdapter() {
				public void internalFrameActivated(InternalFrameEvent e) {
					treeHelper.updateJTreeSelection();
				}
			});
			
			jFrameMap.setLocation( 0, 0 );
			jFrameData.setLocation( 30, 30 );	
			jFrameCartographicDisplay.setLocation( 60, 60 );
			jFrameAnnotations.setLocation( 90, 90 );
			jFrameWizard.setLocation( 0, 0 );
			
			jFrameMap.setVisible(true);			
			jFrameData.setVisible( true );
			jFrameCartographicDisplay.setVisible( true );
			jFrameAnnotations.setVisible( true );
			
			treeHelper.updateJTreeSelection();
				
		}
		return jDesktopPane;
	}
	
	/**
	 * This method initializes jScrollPaneLeft
	 * 
	 * @return javax.swing.JScrollPane
	 */
	private JScrollPane getJScrollPaneLeft() {
		if ( jScrollPaneLeft == null ) {
			jScrollPaneLeft = new JScrollPane();			
			jScrollPaneLeft.setViewportView(getJTree());
		}
		return jScrollPaneLeft;
	}
	
	private JTree getJTree() {
		return treeHelper.getJTree();
	}
	
	private JPanel getJPanelLeft() {
		if ( jPanelLeft == null ) {
			jPanelLeft = new JPanel();
			jPanelLeft.setLayout( new BorderLayout() );
			jPanelLeft.add( getJScrollPaneLeft(), BorderLayout.CENTER );
		}
		return jPanelLeft;
	}
	
	private JPanel getJPanelRight() {
		if ( jPanelRight == null ) {
			jPanelRight = new JPanel();
			jPanelRight.setLayout( new BoxLayout(jPanelRight, BoxLayout.Y_AXIS) );
			jPanelRight.add( getJDesktopPane(), null );
		}
		return jPanelRight;
	}	

	public JPopupMenu getJPopupMenuAnnotations() {
		if ( jPopupMenuAnnotations == null ) {
			jPopupMenuAnnotations =new JPopupMenu();
			jPopupMenuAnnotations.add(getJMenuItemAnnotationsNew());
			jPopupMenuAnnotations.add(getJMenuItemAnnotationsOpen());
			jPopupMenuAnnotations.add(getJCheckBoxMenuItemAnnotationsEdit());			
			jPopupMenuAnnotations.add(getJMenuItemAnnotationsSave());
			jPopupMenuAnnotations.add(getJMenuItemAnnotationsSaveAs());
		}
		
		return jPopupMenuAnnotations;
	}

	public JPopupMenu getJPopupMenuData() {
		if ( jPopupMenuData == null ) {
			jPopupMenuData =new JPopupMenu();
			jPopupMenuData.add(getJMenuItemAttributesNew());
			jPopupMenuData.add(getJMenuItemAttributesOpen());
			jPopupMenuData.add(getJCheckBoxMenuItemDataEdit());
			jPopupMenuData.add(getJMenuItemDataEditStructure());			
			jPopupMenuData.add(getJMenuItemAttributesSave());
			jPopupMenuData.add(getJMenuItemAttributesSaveAs());
			jPopupMenuData.add(getJMenuItemAttributesReloadFromDataSource());
			jPopupMenuData.addSeparator();			
			jPopupMenuData.add(getJMenuItemAttributesImport());
			jPopupMenuData.add(getJMenuItemDataCreatePointEntryStructure());
			jPopupMenuData.add(getJMenuItemDataCreateAndPopulateWithJoinId());			
			jPopupMenuData.addSeparator();
			jPopupMenuData.add(getJMenuItemAttributesPrint());
		}		
		return jPopupMenuData;
	}

	public JPopupMenu getJPopupMenuBaseMap() {
		if ( jPopupMenuBaseMap == null ) {
			jPopupMenuBaseMap =new JPopupMenu();

			jPopupMenuBaseMap.add(getJMenuItemBaseMapNew());
			jPopupMenuBaseMap.add(getJMenuItemBaseMapOpen());
			jPopupMenuBaseMap.add(getJCheckBoxMenuItemBaseMapEdit());					
			jPopupMenuBaseMap.add(getJMenuItemBaseMapSave());
			jPopupMenuBaseMap.add(getJMenuItemBaseMapSaveAs());
			jPopupMenuBaseMap.addSeparator();	
			jPopupMenuBaseMap.add(getJMenuItemBaseMapProject());
	
		}		
		return jPopupMenuBaseMap;
	}

	public JPopupMenu getJPopupMenuCartographicDisplay() {
		if ( jPopupMenuCartographicDisplay == null ) {
			jPopupMenuCartographicDisplay =new JPopupMenu();
			jPopupMenuCartographicDisplay.add(getJMenuItemCartographicDisplayNew());
			jPopupMenuCartographicDisplay.add(getJMenuItemCartographicDisplayOpen());
			jPopupMenuCartographicDisplay.add(getJMenuItemCartographicDisplayEditNonMatchingInformation());			
			jPopupMenuCartographicDisplay.add(getJMenuItemCartographicDisplaySave());
			jPopupMenuCartographicDisplay.add(getJMenuItemCartographicDisplaySaveAs());
		}		
		return jPopupMenuCartographicDisplay;
	}

	public JPopupMenu getJPopupMenuThematicMap() {
		if ( jPopupMenuThematicMap == null ) {
			jPopupMenuThematicMap =new JPopupMenu();
			jPopupMenuThematicMap.add(getJMenuItemThematicMapNew());
			jPopupMenuThematicMap.add(getJMenuItemThematicMapOpen());
			jPopupMenuThematicMap.add(getJMenuItemThematicMapSave());
			jPopupMenuThematicMap.add(getJMenuItemThematicMapSaveAs());
			jPopupMenuThematicMap.addSeparator();			
			jPopupMenuThematicMap.add(getJMenuItemThematicMapWizard());	
			jPopupMenuThematicMap.add(getJMenuItemThematicMapFullScreen());			
			jPopupMenuThematicMap.addSeparator();
			jPopupMenuThematicMap.add(getJMenuItemThematicMapClipboardCopy());			
			jPopupMenuThematicMap.add(getJMenuItemThematicMapPrint());
			jPopupMenuThematicMap.addSeparator();	
			jPopupMenuThematicMap.add(getJMenuItemThematicMapProperties());			

		}			
		return jPopupMenuThematicMap;
	}
	
	private JMenuItem getJMenuItemThematicMapFullScreen() {
		if (jMenuItemThematicMapFullScreen == null) {
			jMenuItemThematicMapFullScreen = new JMenuItem();
			jMenuItemThematicMapFullScreen.setText("Full screen...");
			jMenuItemThematicMapFullScreen.setMnemonic( 'F' );
			jMenuItemThematicMapFullScreen
					.addActionListener(new ActionListener() {
						public void actionPerformed(ActionEvent e) {
							displayThematicMapFullScreen();
						}
					});
		}
		return jMenuItemThematicMapFullScreen;
	}
	
	public void displayThematicMapFullScreen() {
		final JFrameThematicMapFullScreen dlg =new JFrameThematicMapFullScreen();
		jFrameMap.getMappingToolKit().fitToWindow();
		jFrameMap.resetZoom();
		//dlg.show();
		
		dlg.addWindowListener( new WindowAdapter() {
			public void windowOpened(WindowEvent e) {
				BufferedImage bi =jFrameMap.getMappingToolKit().retrieveThematicMapImage( dlg.getScreenDimension().width
					    , dlg.getScreenDimension().height );
				dlg.setImage( bi );
			}
		} );
		
		dlg.setVisible( true );

	}	

	private JMenuItem getJMenuItemCartographicDisplayNew() {
		if(jMenuItemCartographicDisplayNew == null) {
			jMenuItemCartographicDisplayNew = new JMenuItem();
			jMenuItemCartographicDisplayNew.setText("New");		
			jMenuItemCartographicDisplayNew.setMnemonic( 'N' );
			jMenuItemCartographicDisplayNew
					.addActionListener(new ActionListener() {
						public void actionPerformed(ActionEvent e) {
							CartographicDisplay cd =cdUIHelper.newCD( thisFrame );
							thematicMap.setCartographicDisplay( cd );
							jFrameCartographicDisplay.refreshData();
						}
					});
		}
		return jMenuItemCartographicDisplayNew;
	}
	
	private JMenuItem getJMenuItemThematicMapNew() {
		if(jMenuItemThematicMapNew == null) {
			jMenuItemThematicMapNew = new JMenuItem();
			jMenuItemThematicMapNew.setText("New");
			jMenuItemThematicMapNew.setMnemonic('N');
			jMenuItemThematicMapNew.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					newThematicMap();
				}
			});
		}
		return jMenuItemThematicMapNew;
	}
	
	public void newThematicMap() {
		thematicMapUIHelper.newThematicMap( getContentPane() );
	}
	
	private JMenuItem getJMenuItemBaseMapNew() {
		if(jMenuItemBaseMapNew == null) {
			jMenuItemBaseMapNew = new JMenuItem();
			jMenuItemBaseMapNew.setText("New");
			jMenuItemBaseMapNew.setMnemonic( 'N' );			
			jMenuItemBaseMapNew.addActionListener(new ActionListener() { 
				public void actionPerformed(ActionEvent e) {
				    newMap();
				}
			});
		}
		return jMenuItemBaseMapNew;
	}
	
	public void newMap() {
		baseMapUIHelper.newBaseMap( jFrameMap );
		resetEditMode();
	}

	private JMenuItem getJMenuItemThematicMapOpen() {
		if(jMenuItemThematicMapOpen == null) {
			jMenuItemThematicMapOpen = new JMenuItem();
			jMenuItemThematicMapOpen.setText("Open...");
			jMenuItemThematicMapOpen.setMnemonic( 'O' );			
			jMenuItemThematicMapOpen.addActionListener(new ActionListener() { 
				public void actionPerformed(ActionEvent e) {
					openThematicMap();
				}
			});
		}
		return jMenuItemThematicMapOpen;
	}
	
	public void openThematicMap() {
		ThematicMap loadedMap =(ThematicMap)thematicMapUIHelper.open( getJContentPane(), thematicMap );
		
		if ( loadedMap != null ) {
			jFrameMap.getMappingToolKit().setDbaseJoinIdx( loadedMap.getBaseMap().getDbaseJoinIdx() );
			thematicMap =loadedMap;
			thematicMapUIHelper.setThematicMapName( thematicMap.getFile() );
			
			thematicMapUIHelper.applyThematicMap( thisFrame );
		}
	}
	
	private JMenuItem getJMenuItemBaseMapOpen() {
		if(jMenuItemBaseMapOpen == null) {
			jMenuItemBaseMapOpen = new JMenuItem();
			jMenuItemBaseMapOpen.setText("Open/Add...");
			jMenuItemBaseMapOpen.setMnemonic( 'O' );
			jMenuItemBaseMapOpen.addActionListener(new ActionListener() { 
				public void actionPerformed(ActionEvent e) {    
					openMap();
				}
			});
		}
		return jMenuItemBaseMapOpen;
	}
	
	public void openMap()  {
		StringBuilder polygonColumnName =new StringBuilder();
		StringBuilder dataColumnName =new StringBuilder();		
			
		try {			
			File file =baseMapUIHelper.openBaseMap( getJContentPane(), jFrameMap, polygonColumnName );
		    if (  file != null ) {
		    	if ( polygonColumnName.length() != 0 
		    			&& dataUIHelper.usePolygonNameForAttrs( 
		    										 JOptionPane.getFrameForComponent( this ), 
		    										 jFrameMap.getMappingToolKit().getShapes(), 
		    										 polygonColumnName, dataColumnName, 
		    										 (DataTableDataModel)jFrameData.getJTable().getModel()) ) {
		        	thematicMap.setData( ((DataTableDataModel)jFrameData.getJTable().getModel()).getAttrs() );
		    		//jFrameData.notifyObservers();
		    		EventBus.publish( new DataStructureHasChanged( ((DataTableDataModel)jFrameData.getJTable().getModel()).getAttrs().getHeader() ) );
		    		
		    		thematicMap.setBaseMap( jFrameMap.getMappingToolKit().retrieveBaseMap() );
		    		thematicMap.getBaseMap().setFile( file );
		    		
		    		thematicMap.getCartographicDisplay().setJoinIdColumnName( polygonColumnName.toString() );
		    		thematicMap.getCartographicDisplay().setDataColumnName( dataColumnName.toString() );		    		
		    		
		    		thematicMapUIHelper.applyThematicMap( thisFrame );
		    	}
		    	jFrameMap.repaint();
		    }
		} catch (Exception e) {
	        miscUIHelper.displayErrorMessage( thisFrame.getContentPane(), e );
		}	    
	}
	
	private JMenuItem getJMenuItemAttributesNew() {
		if(jMenuItemDataNew == null) {
			jMenuItemDataNew = new JMenuItem();
			jMenuItemDataNew.setText("New");
			jMenuItemDataNew.setMnemonic( 'N' );
			jMenuItemDataNew.addActionListener(new ActionListener() { 
				public void actionPerformed(ActionEvent e) {
					newData();
				}
			});
		}
		return jMenuItemDataNew;
	}
	
	public void newData() {
	    DataTableDataModel dataModel =(DataTableDataModel)jFrameData.getJTable().getModel();

	    dataUIHelper.newAttributes( thisFrame, dataModel );
	    
	    thematicMap.setData( dataModel.getAttrs() );
	    thematicMap.setDirty( true );
	    
	    //jFrameData.notifyObservers();
		EventBus.publish( new DataStructureHasChanged( dataModel.getAttrs().getHeader() ) );
	}
	
	private JMenuItem getJMenuItemAttributesOpen() {
		if ( jMenuItemDataOpen == null ) {
			jMenuItemDataOpen = new JMenuItem();
			jMenuItemDataOpen.setText("Open...");
			jMenuItemDataOpen.setMnemonic( 'O' );			
			jMenuItemDataOpen.addActionListener(new ActionListener() { 
				public void actionPerformed(ActionEvent e) { 
					openData();
				}
			});
		}
		return jMenuItemDataOpen;
	}
	
	public void openData() {
		   
		try {
		    DataTableDataModel dataModel =(DataTableDataModel)jFrameData.getJTable().getModel();
	
		    boolean attrLoaded =dataUIHelper.openAttributes( getJContentPane(), dataModel );
	
		    if ( attrLoaded ) {
		    	thematicMap.setDirty( true );
		    }
		    
	    	thematicMap.setData( dataModel.getAttrs() );				    
	
		   // jFrameData.notifyObservers();
    		EventBus.publish( new DataStructureHasChanged( dataModel.getAttrs().getHeader() ) );
		} catch (Exception e) {
			miscUIHelper.displayErrorMessage( this, e );
		}
	}
	
	private JMenuItem getJMenuItemBaseMapSave() {
		if(jMenuItemBaseMapSave == null) {
			jMenuItemBaseMapSave = new JMenuItem();
			jMenuItemBaseMapSave.setText("Save");
			jMenuItemBaseMapSave.setMnemonic( 'S' );				
			jMenuItemBaseMapSave.addActionListener(new ActionListener() { 
				public void actionPerformed(ActionEvent e) {    
				    baseMapUIHelper.saveBaseMap( getContentPane(), jFrameMap );
				}
			});
		}
		return jMenuItemBaseMapSave;
	}

	private JMenuItem getJMenuItemThematicMapSave() {
		if(jMenuItemThematicMapSave == null) {
			jMenuItemThematicMapSave = new JMenuItem();
			jMenuItemThematicMapSave.setText("Save");
			jMenuItemThematicMapSave.setMnemonic('S');
			jMenuItemThematicMapSave.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					saveThematicMap();

				}
			});
		}
		return jMenuItemThematicMapSave;
	}
	
	public void saveThematicMap() {
		try {
			// STL 2009.09.04
			thematicMap.setBaseMap( jFrameMap.getMappingToolKit().retrieveBaseMap() );
			
			if ( thematicMap.getBaseMap() != null ) {
				File baseMapFile =thematicMap.getBaseMap().getFile();
				thematicMap.setBaseMap( jFrameMap.getMappingToolKit().retrieveBaseMap() );
				thematicMap.getBaseMap().setFile( baseMapFile );
				File file =thematicMapUIHelper.save( getJContentPane(), thematicMap
												   , jFrameMap.getJPanel().getWidth()
												   , jFrameMap.getJPanel().getHeight() );
				
				if ( file != null ) {
					thematicMapUIHelper.setThematicMapName( file );
				}
			}
		} catch (TMapException e1) {
			miscUIHelper.displayErrorMessage( this, e1 );
		}		
	}
	
	private JMenuItem getJMenuItemThematicMapSaveAs() {
		if(jMenuItemThematicMapSaveAs == null) {
			jMenuItemThematicMapSaveAs = new JMenuItem();
			jMenuItemThematicMapSaveAs.setText("Save As...");
			jMenuItemThematicMapSaveAs.setMnemonic( 'A' );
			jMenuItemThematicMapSaveAs.addActionListener(new ActionListener() {   
				public void actionPerformed(ActionEvent e) {
					saveThematicMapAs();
				} 
			});					
		}
		return jMenuItemThematicMapSaveAs;
	}
	
	public void saveThematicMapAs() {
		try {
			thematicMap.setBaseMap( jFrameMap.getMappingToolKit().retrieveBaseMap() );
			
			File file =thematicMapUIHelper.saveAs( getJContentPane(), thematicMap
												 , jFrameMap.getJPanel().getWidth()
												 , jFrameMap.getJPanel().getHeight() );
			
			if ( file != null ) {
				thematicMapUIHelper.setThematicMapName( file );
			}
		} catch (TMapException e1) {
			miscUIHelper.displayErrorMessage( thisFrame, e1 );
		}	
	}
	
	private JMenuItem getJMenuItemBaseMapSaveAs() {
		if(jMenuItemBaseMapSaveAs == null) {
			jMenuItemBaseMapSaveAs = new JMenuItem();
			jMenuItemBaseMapSaveAs.setText("Save As...");
			jMenuItemBaseMapSaveAs.setMnemonic( 'A' );
			jMenuItemBaseMapSaveAs.addActionListener(new ActionListener() { 
				public void actionPerformed(ActionEvent e) {    				
				    baseMapUIHelper.saveBaseMapAs( getContentPane(), jFrameMap );
				}
			});				
		}
		return jMenuItemBaseMapSaveAs;
	}
	
	private JMenuItem getJMenuItemBaseMapProject() {
		if(jMenuItemBaseMapProject == null) {
			jMenuItemBaseMapProject = new JMenuItem();
			jMenuItemBaseMapProject.setText("Winkel Tripel Projection");
			jMenuItemBaseMapProject.setMnemonic( 'P' );
			jMenuItemBaseMapProject.addActionListener(new ActionListener() { 
				public void actionPerformed(ActionEvent e) {    				
				    //baseMapUIHelper.saveBaseMapAs( getContentPane(), jFrameMap );
					jFrameMap.getMappingToolKit().projectShapes();
				}
			});				
		}
		return jMenuItemBaseMapProject;
	}	
	
	private JMenuItem getJMenuItemAttributesSave() {
		if(jMenuItemDataSave == null) {
			jMenuItemDataSave = new JMenuItem();
			jMenuItemDataSave.setText("Save");
			jMenuItemDataSave.setMnemonic( 'S' );
			jMenuItemDataSave.addActionListener(new ActionListener() { 
				public void actionPerformed(ActionEvent e) {
				    Attrs attrs =((DataTableDataModel)jFrameData.getJTable()
				    										.getModel()).getAttrs();

				    if ( attrs.getFile() == null ) {
				        dataUIHelper.saveAttributesAs( getJContentPane(), attrs );
				    } else {			        
				        dataUIHelper.saveAttributes( thisFrame, attrs.getFile(), attrs );
				    }
				}
			});
		}
		return jMenuItemDataSave;
	}
	
	private JMenuItem getJMenuItemAttributesSaveAs() {
		if(jMenuItemDataSaveAs == null) {
			jMenuItemDataSaveAs = new JMenuItem();
			jMenuItemDataSaveAs.setText("Save As...");
			jMenuItemDataSaveAs.setMnemonic( 'A' );
			jMenuItemDataSaveAs.addActionListener(new ActionListener() { 
				public void actionPerformed(ActionEvent e) {    
				    dataUIHelper.saveAttributesAs( getJContentPane(), 
				            ((DataTableDataModel)jFrameData.getJTable().getModel()).getAttrs()
				    );			

				}
			});		
			
		}
		return jMenuItemDataSaveAs;
	}

	private JMenuItem getJMenuItemAnnotationsNew() {
		if(jMenuItemAnnotationsNew == null) {
			jMenuItemAnnotationsNew = new JMenuItem();
			jMenuItemAnnotationsNew.setText("New");
			jMenuItemAnnotationsNew.setMnemonic( 'N' );
			jMenuItemAnnotationsNew.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					Annotations annotations =annUIHelper.newAnnotations( thisFrame );
					thematicMap.setAnnotations( annotations );
					jFrameAnnotations.refreshData();	
				}
			});
		}
		return jMenuItemAnnotationsNew;
	}
	
	private JMenuItem getJMenuItemAnnotationsOpen() {
		if(jMenuItemAnnotationsOpen == null) {
			jMenuItemAnnotationsOpen = new JMenuItem();
			jMenuItemAnnotationsOpen.setText("Open...");
			jMenuItemAnnotationsOpen.setMnemonic( 'O' );			
			jMenuItemAnnotationsOpen.addActionListener(new ActionListener() { 
				public void actionPerformed(ActionEvent e) {    
					Annotations annotations =annUIHelper.openAnnotations( getContentPane() );
					if ( annotations != null ) {
						thematicMap.setAnnotations( annotations );

						try {
							jFrameMap.getMappingToolKit().addShapes( annotations.getGraphics() );
						} catch (TMapException e1) {
							logger.error( e1 );
						}
						
						jFrameAnnotations.refreshData();
					}
				}
			});

		}
		return jMenuItemAnnotationsOpen;
	}
	
	private JMenuItem getJMenuItemAnnotationsSave() {
		if(jMenuItemAnnotationsSave == null) {
			jMenuItemAnnotationsSave = new JMenuItem();
			jMenuItemAnnotationsSave.setText("Save");
			jMenuItemAnnotationsSave.setMnemonic( 'S' );
			jMenuItemAnnotationsSave.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					try {
						Annotations annotations =jFrameAnnotations.retrieveAnnotations();

					    annUIHelper.saveAnnotations( getJContentPane(), annotations.getFile(), annotations );								
					} catch (Exception e1) {
						miscUIHelper.displayErrorMessage( thisFrame, e1 );
					}				
				}
			});
		}
		return jMenuItemAnnotationsSave;
	}
	
	private JMenuItem getJMenuItemAnnotationsSaveAs() {
		if(jMenuItemAnnotationsSaveAs == null) {
			jMenuItemAnnotationsSaveAs = new JMenuItem();
			jMenuItemAnnotationsSaveAs.setText("Save As...");
			jMenuItemAnnotationsSaveAs.setMnemonic( 'A' );
			jMenuItemAnnotationsSaveAs.addActionListener(new ActionListener() { 
				public void actionPerformed(ActionEvent e) {    
				    annUIHelper.saveAnnotationsAs(  
				            getJContentPane(), 
				            jFrameAnnotations.retrieveAnnotations()
				    );			
	
				}
			});		
		}
		return jMenuItemAnnotationsSaveAs;
	}
	
	private JMenuItem getJMenuItemCartographicDisplayOpen() {
		if(jMenuItemCartographicDisplayOpen == null) {
			jMenuItemCartographicDisplayOpen = new JMenuItem();
			jMenuItemCartographicDisplayOpen.setText("Open...");
			jMenuItemCartographicDisplayOpen.setMnemonic( 'O' );			
			jMenuItemCartographicDisplayOpen.addActionListener(new ActionListener() { 
				public void actionPerformed(ActionEvent e) {    
					CartographicDisplay cd =cdUIHelper.openCD( getContentPane() );
					thematicMap.setCartographicDisplay( cd );
					jFrameCartographicDisplay.refreshData();
				}
			});			
		}
		return jMenuItemCartographicDisplayOpen;
	}
	
	private JMenuItem getJMenuItemCartographicDisplaySave() {
		if(jMenuItemCartographicDisplaySave == null) {
			jMenuItemCartographicDisplaySave = new JMenuItem();
			jMenuItemCartographicDisplaySave.setText("Save");
			jMenuItemCartographicDisplaySave.setMnemonic( 'S' );
			jMenuItemCartographicDisplaySave
					.addActionListener(new ActionListener() {
						public void actionPerformed(ActionEvent e) {

							try {
								CartographicDisplay cd = jFrameCartographicDisplay.getCartographicDisplay();
								thematicMap.setCartographicDisplay( cd );
							    cdUIHelper.saveCD( getJContentPane(), cd.getFile(), cd );								
							} catch (TMapException e1) {
								miscUIHelper.displayErrorMessage( thisFrame, e1 );
							}
			
						}
					});
		}
		return jMenuItemCartographicDisplaySave;
	}
	
	private JMenuItem getJMenuItemCartographicDisplaySaveAs() {
		if(jMenuItemCartographicDisplaySaveAs == null) {
			jMenuItemCartographicDisplaySaveAs = new JMenuItem();
			jMenuItemCartographicDisplaySaveAs.setText("Save As...");
			jMenuItemCartographicDisplaySaveAs.setMnemonic( 'A' );
			jMenuItemCartographicDisplaySaveAs.addActionListener(new ActionListener() { 
				public void actionPerformed(ActionEvent e) {    
				    cdUIHelper.saveCDAs( getJContentPane(), thematicMap.getCartographicDisplay() );			
				    
				}
			});
			
		}
		return jMenuItemCartographicDisplaySaveAs;
	}
	
	private JMenuItem getJMenuItemAttributesPrint() {
		if(jMenuItemDataPrint == null) {
			jMenuItemDataPrint = new JMenuItem();
			jMenuItemDataPrint.setText("Print");
			jMenuItemDataPrint.setMnemonic( 'P' );
			jMenuItemDataPrint.addActionListener(new ActionListener() { 
				public void actionPerformed(ActionEvent e) {    
			        PrinterJob pj=PrinterJob.getPrinterJob();

					pj.setPrintable(jFrameData);
					pj.printDialog();

					try { 
					    pj.print();
					} catch (Exception printException) {
					    miscUIHelper.displayErrorMessage( thisFrame, printException );
					}
				}				
			});
		}
		return jMenuItemDataPrint;
	}
	
	private JMenuItem getJMenuItemAttributesReloadFromDataSource() {
		if (jMenuItemDataReload == null) {
			jMenuItemDataReload = new JMenuItem();
			jMenuItemDataReload.setText("Reload from data source...");
			jMenuItemDataReload.setMnemonic( 'R' );
			jMenuItemDataReload.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					reloadFromDataSource( true );
				}
			});
		}
		return jMenuItemDataReload;
	}	
	
	public void reloadFromDataSource( boolean useUI ) {
		if ( thematicMap.getData().getDsProperties() == null || thematicMap.getData().getDsProperties().size() == 0 ) {
			
			String msg ="There is no data source information to reload.";
			if ( useUI ) {
				miscUIHelper.displayErrorMessage( this, msg );
			} else {
				System.out.println( msg );
			}
			
		} else {
			try {
	            int n =JOptionPane.YES_OPTION;
	            	
	            if ( useUI ) {
	            	JOptionPane.showConfirmDialog( thisFrame,
	                    "This operation will erase your current data.\nDo you want to continue ?",
	                    "Reload data from data source",
	                    JOptionPane.YES_NO_OPTION);
	            }
	            
	            if ( n == JOptionPane.YES_OPTION ) {
					DataTableDataModel dataModel =(DataTableDataModel)jFrameData.getJTable().getModel();
					Attrs attrs =dataUIHelper.reloadFromDataSource( this
																  , dataModel.getAttrs().getDsProperties()
																  , useUI );

					if ( attrs != null ) {
						dataModel.setAttrs( attrs );
		
				    	thematicMap.setDirty( true );
				    	thematicMap.setData( dataModel.getAttrs() );
				    	//jFrameData.notifyObservers();
			    		EventBus.publish( new DataStructureHasChanged( dataModel.getAttrs().getHeader() ) );
				    	
			    		thematicMapUIHelper.applyThematicMap( thisFrame );
					}
	            }
	            
			} catch( Exception e ) {
				String msg ="Reload from data source has failed:" + e.toString();
				if ( useUI ) {
					miscUIHelper.displayErrorMessage( this, msg );
				} else {
					System.out.println( msg );
				}
			}
		}
	}
	
 
	private JMenuItem getJMenuItemAttributesImport() {
		if (jMenuItemDataImport == null) {
			jMenuItemDataImport = new JMenuItem();
			jMenuItemDataImport.setText("Import Wizard...");
			jMenuItemDataImport.setMnemonic( 'W' );
			jMenuItemDataImport.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					importData();
				}
			});
		}
		return jMenuItemDataImport;
	}
	
	public void importData() {
		
	    DataTableDataModel dataModel =(DataTableDataModel)jFrameData.getJTable().getModel();
	    if ( dataUIHelper.importAttributes( dataModel, JOptionPane.getFrameForComponent( thisFrame ) ) ) {
	    	thematicMap.setDirty( true );
	    	thematicMap.setData( dataModel.getAttrs() );
	    	//jFrameData.notifyObservers();
    		EventBus.publish( new DataStructureHasChanged( dataModel.getAttrs().getHeader() ) );
	    }
	}
	
	public void clipboardCopy() {
	    try {
		    cursorHelper.setCursor(this, CursorHelper.Cursors.WAIT );	    
		    jFrameMap.getMappingToolKit().clipboardCopy();
	    } catch( Throwable e ) {
	        // Potentially an out of memory exception
	    	miscUIHelper.displayErrorMessage( this, e.toString() );
	    /*} catch( Error err ) {
	        // Potentially an out of memory exception
	    	miscUIHelper.displayErrorMessage( this, err.getMessage() );*/
	    } finally {
	        cursorHelper.setPreviousCursor( this );
	    }
	        
	}
	
	private void setFrameToNormal( JInternalFrame frame ) throws PropertyVetoException {
		if ( frame.isIcon() ) {
			frame.setIcon( false );
		}
		
		if ( frame.isMaximum() ) {
			frame.setMaximum( false );
		}
	}
	
	public void tileVertically() {
		
		int width =getJDesktopPane().getWidth();
		int height =getJDesktopPane().getHeight();
		
		int halfHeight =height / 2;
		int thirdWidth =width / 3;
		
		try {	
			setFrameToNormal( jFrameMap );			
			jFrameMap.setBounds( 0, 0, width, halfHeight );

			setFrameToNormal( jFrameData );						
			jFrameData.setBounds( 0, halfHeight + 1, thirdWidth, halfHeight );
			
			setFrameToNormal( jFrameCartographicDisplay );			
			jFrameCartographicDisplay.setBounds( thirdWidth + 1, halfHeight + 1, thirdWidth, halfHeight );
			
			setFrameToNormal( jFrameAnnotations );			
			jFrameAnnotations.setBounds( ( thirdWidth * 2 ) + 1, halfHeight + 1, thirdWidth, halfHeight );

			jFrameMap.setSelected(true);
		} catch (PropertyVetoException e) {
			logger.error(e);
		}
		
		getJDesktopPane().revalidate();
		getJDesktopPane().repaint();		
	
		getJSplitPane().validate();		
	}
	
	public void tileHorizontally() {
		
		int width =getJDesktopPane().getWidth();
		int height =getJDesktopPane().getHeight();		
		
		int halfWidth =width / 2;
		int thirdHeight =height / 3;
		
		try {		
			setFrameToNormal( jFrameMap );			
			jFrameMap.setBounds( 0, 0, halfWidth, height);

			setFrameToNormal( jFrameData );			
			jFrameData.setBounds( halfWidth +1, 0, halfWidth, thirdHeight );

			setFrameToNormal( jFrameCartographicDisplay );			
			jFrameCartographicDisplay.setBounds( halfWidth +1, thirdHeight +1, halfWidth, thirdHeight );

			setFrameToNormal( jFrameAnnotations );			
			jFrameAnnotations.setBounds( halfWidth +1, thirdHeight*2 +1, halfWidth, thirdHeight );

			jFrameMap.setSelected(true);
		} catch (PropertyVetoException e) {
			logger.error(e);
		}
		
		getJDesktopPane().revalidate();
		getJDesktopPane().repaint();		
	
		getJSplitPane().validate();			
	}	
	
	public void setAutoResize( boolean autoResize ) {
		enableAutoResize =autoResize;
		

	}
	
	public void initPreviousSize() {
		previousSize =new Dimension( getJDesktopPane().getWidth(), getJDesktopPane().getHeight() );
	}
	
	public void rearrangeWindowsAfterResize() {
		
		Dimension currentSize =new Dimension( getJDesktopPane().getWidth(), getJDesktopPane().getHeight() );		
//		logger.debug( "jDesktopPane.currentSize=" + currentSize );		
		
		if ( enableAutoResize ) {

//			logger.debug( "previousSize=" + previousSize );
					
			if ( previousSize != null ) {	
								 
				double widthRatio =previousSize.getWidth() != 0 && currentSize.getWidth() != 0 
											? currentSize.getWidth() / previousSize.getWidth() : 1.0;
				double heightRatio =previousSize.getWidth() != 0 && currentSize.getWidth() != 0 
											? currentSize.getHeight() / previousSize.getHeight() : 1.0;
				
//				logger.debug( "widthRatio=" + widthRatio );
//				logger.debug( "heightRatio=" + heightRatio );			
				
				rearrangeFrame( jFrameMap, widthRatio, heightRatio );
				rearrangeFrame( jFrameData, widthRatio, heightRatio );	
				rearrangeFrame( jFrameCartographicDisplay, widthRatio, heightRatio );	
				rearrangeFrame( jFrameAnnotations, widthRatio, heightRatio );
			}

			if ( currentSize.width != 0 && ( previousSize == null || previousSize.getWidth() != 0 ) ) {
				previousSize =currentSize;
			}
		}
		
	}
	
	private void rearrangeFrame( JInternalFrame frame, double widthRatio, double heightRatio ) {
		int x =(int)Math.round((double)frame.getX() * widthRatio);
		int y =(int)Math.round((double)frame.getY() * heightRatio);	
		int width =(int)Math.round((double)frame.getWidth() * widthRatio);
		int height =(int)Math.round((double)frame.getHeight() * heightRatio);			
		
		frame.setBounds( x, y, width, height );
	}
	
	public void startWizardMode() {
		if ( thematicMapUIHelper.newThematicMap( getContentPane() ) == JOptionPane.CANCEL_OPTION ) {
			return;		
		}
		
		if ( !jFrameWizard.isVisible() ) {
			splitPaneDividerLocation =getJSplitPane().getDividerLocation();
			splitPaneDividerSize =getJSplitPane().getDividerSize();
			
			getJSplitPane().setDividerLocation(0);
			getJSplitPane().setDividerSize(0);
			getJSplitPane().validate();
			jFrameWizard.setVisible( true );
			
			jFrameData.setVisible( false );
			jFrameCartographicDisplay.setVisible( false );
			jFrameAnnotations.setVisible( false );
			
			jFrameMap.enableWizardMode( true );
			jFrameData.enableWizardMode( true );
			jFrameCartographicDisplay.enableWizardMode( true );			
		}
		
		jFrameWizard.startWizard();
	}
	
	public void stopWizardMode() {

		jFrameWizard.setBounds( 0, 0, 10, 10 );
		jFrameWizard.setVisible( false );
		jFrameMap.setVisible( true );
		jFrameData.setVisible( true );
		jFrameCartographicDisplay.setVisible( true );
		jFrameAnnotations.setVisible( true );
		
		jFrameMap.enableWizardMode( false );
		jFrameData.enableWizardMode( false );
		jFrameCartographicDisplay.enableWizardMode( false );
		
		try {
			jFrameMap.setSelected( true );
		} catch (PropertyVetoException e) {
			logger.error( e );
		}
		
		getJSplitPane().setDividerSize( splitPaneDividerSize );	
		getJSplitPane().setDividerLocation( splitPaneDividerLocation );
		getJSplitPane().validate();
		
		getJDesktopPane().setPreferredSize( new Dimension( 50, 50) );
		getJDesktopPane().revalidate();
		getJDesktopPane().repaint();
		
		tileVertically();

	}

	public void displayWizardFrame( int frameId ) throws PropertyVetoException {
		switch( frameId ) {
		
			case JFrameWizard.MAP_SCREEN:
				arrangeWizardFrames( jFrameMap );
				break;
				
			case JFrameWizard.ATTRIBUTES_SCREEN:
				arrangeWizardFrames( jFrameData );
				break;
				
			case JFrameWizard.CD_SCREEN:
				arrangeWizardFrames( jFrameCartographicDisplay );
				break;				
				
			case JFrameWizard.WIZARD_FINISH_SCREEN:
				arrangeWizardFrames( jFrameMap );
				break;				
		}
	}
	
	public void arrangeWizardFrames( JInternalFrame jFrame ) {
		int quarterHeight =( getJDesktopPane().getHeight() / 4 ) -1;
		int width =getJDesktopPane().getWidth() -1;

		jFrameWizard.setBounds( 0, ( quarterHeight * 3 ) + 1, width, quarterHeight );		
		
		if ( jFrame != null ) {
			jFrame.setVisible( true );
			jFrame.setBounds( 0, 0, width, quarterHeight * 3 );
			try {
				jFrame.setSelected(true);
			} catch (PropertyVetoException e) {
				logger.error(e);
			}	
		} else {

			jFrameMap.setVisible( false );
			jFrameData.setVisible( false );
			jFrameCartographicDisplay.setVisible( false );
			jFrameAnnotations.setVisible( false );
		}
	
	}

	private JMenuItem getJMenuItemThematicMapPrint() {
		if (jMenuItemThematicMapPrint == null) {
			jMenuItemThematicMapPrint = new JMenuItem();
			jMenuItemThematicMapPrint.setText("Print...");
			jMenuItemThematicMapPrint.setMnemonic( 'P' );
			jMenuItemThematicMapPrint
					.addActionListener(new ActionListener() {
						public void actionPerformed(ActionEvent e) {
							printThematicMap();
						}
					});
		}
		return jMenuItemThematicMapPrint;
	}
	
	public void printThematicMap() {
		PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();

		aset.add(new Copies(1));
		aset.add(new JobName("TMap thematic map", null));

		/* Create a print job */
		PrinterJob pj = PrinterJob.getPrinterJob();
		if ( pj.getPrintService() != null ) {
			jFrameMap.fitToWindow();
		    pj.setPrintable(jFrameMap.getMappingToolKit());
			
		    try {
				if(pj.printDialog(aset)) {
					pj.print(aset);
				}
			} catch (PrinterException pe) { 
				System.err.println(pe);
			}
			jFrameMap.fitToWindow();	
		} else {
		    miscUIHelper.displayErrorMessage( thisFrame, "No available printer!");
		}		
	}

	private JMenuItem getJMenuItemThematicMapClipboardCopy() {
		if (jMenuItemThematicMapClipboardCopy == null) {
			jMenuItemThematicMapClipboardCopy = new JMenuItem();
			jMenuItemThematicMapClipboardCopy.setText("Clipboard copy");
			jMenuItemThematicMapClipboardCopy.setMnemonic( 'C' );
			jMenuItemThematicMapClipboardCopy.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
				    clipboardCopy();
				}
			});
		}
		return jMenuItemThematicMapClipboardCopy;
	}

	public ThematicMap getThematicMap() {
		return thematicMap;
	}	
	
	public void setThematicMap( ThematicMap thematicMap ) {
		this.thematicMap =thematicMap;
	}		
	
	public ThematicMapUIHelper getThematicMapUIHelper() {
		return thematicMapUIHelper;
	}

	private JMenuItem getJMenuItemThematicMapWizard() {
		if (jMenuItemThematicMapWizard == null) {
			jMenuItemThematicMapWizard = new JMenuItem();
			jMenuItemThematicMapWizard.setMnemonic('w');
			jMenuItemThematicMapWizard.setText("New Thematic Map Wizard...");
			jMenuItemThematicMapWizard
					.addActionListener(new ActionListener() {
						public void actionPerformed(ActionEvent e) {
							startWizardMode();
						}
					});
		}
		return jMenuItemThematicMapWizard;
	}

	private void setEditMode( int editMode ) {
		jFrameMap.setEditMode( editMode );
	}

	public JCheckBoxMenuItem getJCheckBoxMenuItemBaseMapEdit() {
		if (jCheckBoxMenuItemBaseMapEdit == null) {
			jCheckBoxMenuItemBaseMapEdit = new JCheckBoxMenuItem();
			jCheckBoxMenuItemBaseMapEdit.setMnemonic( 'E' );
			jCheckBoxMenuItemBaseMapEdit.setText("Create/Edit");
			jCheckBoxMenuItemBaseMapEdit.addItemListener(new ItemListener() {
				public void itemStateChanged(ItemEvent e) {
					editBaseMap( thisFrame.getJCheckBoxMenuItemBaseMapEdit().isSelected() );
				}
			});
		}
		return jCheckBoxMenuItemBaseMapEdit;
	}
	
	public void editBaseMap( boolean selected ) {
		if ( selected ) {
			thisFrame.setEditMode( thisFrame.jFrameMap.getMappingToolKit().getEditMode() + EditMode.BASE_MAP );
			showEmptyGeographicBoxWarningIfNecessary();
		} else {
			thisFrame.setEditMode( thisFrame.jFrameMap.getMappingToolKit().getEditMode() - EditMode.BASE_MAP );					
		}
		
		if ( thisFrame.jFrameMap.getMappingToolKit().getEditMode() < EditMode.NONE ) {
			thisFrame.setEditMode( EditMode.NONE );
		}
		
		if ( jFrameMain.getJMenuItemEditBaseMap().isSelected() != selected ) {
			jFrameMain.getJMenuItemEditBaseMap().setSelected( selected );
		}

	}
	
	private void showEmptyGeographicBoxWarningIfNecessary() {
		MappingToolKit mtk =jFrameMap.getMappingToolKit();
		if ( mtk.getMinX() == 0 && mtk.getMaxX() == 0 && mtk.getMinY() == 0 && mtk.getMaxY() == 0 && !jFrameMap.isGeoBoxNotInitializedAlreadyWarned() ) {
			JDialogGeoBoxNotInitializedWarning dlg =new JDialogGeoBoxNotInitializedWarning( 
												JOptionPane.getFrameForComponent( thisFrame ), true );
			dlg.setVisible( true );
			
			if ( dlg.editGeoBox ) {
				jFrameMap.editGeographicBox();
			} else {
				jFrameMap.setDefaultGeographicBox();
			}
			
			jFrameMap.setGeoBoxNotInitializedAlreadyWarned( true );			
			
			dlg.dispose();
		}
	}

	public JCheckBoxMenuItem getJCheckBoxMenuItemAnnotationsEdit() {
		if (jCheckBoxMenuItemAnnotationsEdit == null) {
			jCheckBoxMenuItemAnnotationsEdit = new JCheckBoxMenuItem();
			jCheckBoxMenuItemAnnotationsEdit.setText("Edit");
			jCheckBoxMenuItemAnnotationsEdit.setMnemonic( 'E' );
			jCheckBoxMenuItemAnnotationsEdit
					.addItemListener(new ItemListener() {
						public void itemStateChanged(ItemEvent e) {
							editAnnotations( thisFrame.getJCheckBoxMenuItemAnnotationsEdit().isSelected() );
						}
					});
		}
		return jCheckBoxMenuItemAnnotationsEdit;
	}
	
	public void editAnnotations( boolean selected ) {
		if ( selected ) {
			setEditMode( thisFrame.jFrameMap.getMappingToolKit().getEditMode() + EditMode.ANNOTATIONS );
			showEmptyGeographicBoxWarningIfNecessary();
		} else {
			setEditMode( thisFrame.jFrameMap.getMappingToolKit().getEditMode() - EditMode.ANNOTATIONS );				
		}
		
		if ( jFrameMap.getMappingToolKit().getEditMode() < EditMode.NONE ) {
			setEditMode( EditMode.NONE );
		}
		
		jFrameMap.getMappingToolKit().repaint();
		
		if ( jFrameMain.getJMenuItemEditAnnotations().isSelected() != selected ) {
			jFrameMain.getJMenuItemEditAnnotations().setSelected( selected );
		}

	}

	private JMenuItem getJMenuItemThematicMapProperties() {
		if (jMenuItemThematicMapProperties == null) {
			jMenuItemThematicMapProperties = new JMenuItem();
			jMenuItemThematicMapProperties.setText("Properties...");
			jMenuItemThematicMapProperties.setMnemonic( 'r' );			
			jMenuItemThematicMapProperties
					.addActionListener(new ActionListener() {
						public void actionPerformed(ActionEvent e) {
							JDialogThematicMapProperties dlg =new JDialogThematicMapProperties( JOptionPane.getFrameForComponent( thisFrame )
																							  , true
																							  , thisFrame.thematicMap );
							dlg.setVisible( true );
							
							if ( dlg.isSaveButtonPressed() ) {
								if ( thematicMap.getBackgroundImageLinkedFileName() != null
										&& !"".equals( thematicMap.getBackgroundImageLinkedFileName() ) ) {
									jFrameMap.getMappingToolKit().getBackgroundImage()
											 .loadImageFile( new File( thematicMap.getBackgroundImageLinkedFileName() ) );
								}
							}
							
							dlg.dispose();
						}
					});
		}
		return jMenuItemThematicMapProperties;
	}

	public JCheckBoxMenuItem getJCheckBoxMenuItemDataEdit() {
		if (jCheckBoxMenuItemDataEdit == null) {
			jCheckBoxMenuItemDataEdit = new JCheckBoxMenuItem();
			jCheckBoxMenuItemDataEdit.setMnemonic( 'E' );
			jCheckBoxMenuItemDataEdit.setText("Edit");
			jCheckBoxMenuItemDataEdit.addItemListener(new ItemListener() {
				public void itemStateChanged(ItemEvent e) {
					editData( thisFrame.getJCheckBoxMenuItemDataEdit().isSelected() );
				}
			});
			
		}
		return jCheckBoxMenuItemDataEdit;
	}
	
	public void editData( boolean selected ) {
		if ( selected ) {
			thisFrame.setEditMode( thisFrame.jFrameMap.getMappingToolKit().getEditMode() + EditMode.DATA );
			showEmptyGeographicBoxWarningIfNecessary();
		} else {
			thisFrame.setEditMode( thisFrame.jFrameMap.getMappingToolKit().getEditMode() - EditMode.DATA );					
		}
		
		if ( thisFrame.jFrameMap.getMappingToolKit().getEditMode() < EditMode.NONE ) {
			thisFrame.setEditMode( EditMode.NONE );
		}
		
		if ( jFrameMain.getJMenuItemEditData().isSelected() != selected ) {
			jFrameMain.getJMenuItemEditData().setSelected( selected );
		}
	}

	private JMenuItem getJMenuItemDataCreatePointEntryStructure() {
		if (jMenuItemDataCreatePointEntryStructure == null) {
			jMenuItemDataCreatePointEntryStructure = new JMenuItem();
			jMenuItemDataCreatePointEntryStructure.setText("Create Point Entry Structure...");
			jMenuItemDataCreatePointEntryStructure.setMnemonic( 'C' );
			jMenuItemDataCreatePointEntryStructure
					.addActionListener(new ActionListener() {
						public void actionPerformed(ActionEvent e) {
							
							if ( ((String)jFrameCartographicDisplay.getJComboBoxCartographicDisplay().getSelectedItem())
									.equals( CDTypes.names[ CDTypes.POINT ] ) ) {
						
					            int n =JOptionPane.showConfirmDialog( thisFrame,
					                    "This operation will erase your current data & data structure.\nDo you want to continue ?",
					                    "Create Point Entry Structure",
					                    JOptionPane.YES_NO_CANCEL_OPTION);
					            if ( n == JOptionPane.YES_OPTION ) {
					            	jFrameMap.newStructureForPointEntry();
								    thematicMap.setDirty( true );
								    jFrameMap.getMappingToolKit().repaint();
					            }
				            } else {

					            JOptionPane.showMessageDialog(thisFrame,
					            		"Please select the Point cartographic display\nbefore creating a point entry structure...",
					    	            "Create Point Entry Structure",
					    	            JOptionPane.WARNING_MESSAGE);   					    		
					    		
				            }
						}
					});
		}
		return jMenuItemDataCreatePointEntryStructure;
	}

	private JMenuItem getJMenuItemDataCreateAndPopulateWithJoinId() {
		if (jMenuItemDataCreateAndPopulateWithJoinId == null) {
			jMenuItemDataCreateAndPopulateWithJoinId = new JMenuItem();
			jMenuItemDataCreateAndPopulateWithJoinId.setText("Create & Populate With Join ID...");
			jMenuItemDataCreateAndPopulateWithJoinId.setMnemonic( 'J' );
			jMenuItemDataCreateAndPopulateWithJoinId
					.addActionListener(new ActionListener() {
						public void actionPerformed(ActionEvent e) {
							if ( thematicMap.getBaseMap() != null ) {
							
					            int n =JOptionPane.showConfirmDialog( thisFrame,
					                    "This operation will erase your current data & data structure.\nDo you want to continue ?",
					                    "Create & Populate With Join ID",
					                    JOptionPane.YES_NO_CANCEL_OPTION);
					            if ( n == JOptionPane.YES_OPTION ) {
					            	
									try {
										Attrs attrs =new PolygonNamesToAttrsHelper().buildAttrs( 
													 thematicMap.getBaseMap().getShapes()
												  , MapUIHelper.DEFAULT_JOIN_ID_COLUMN_NAME
												  , MapUIHelper.DEFAULT_DATA_COLUMN_NAME
												  , DataUIHelper.DEFAULT_DATA_ATTR_TYPE );
										
								    	// To refresh the data window
								    	DataTableDataModel dataModel =(DataTableDataModel)jFrameData.getJTable().getModel();
								    	dataModel.setAttrs( attrs );							
										
									    thematicMap.setDirty( true );
									    
								    	thematicMap.setData( dataModel.getAttrs() );				    
	
									    //jFrameData.notifyObservers();
							    		EventBus.publish( new DataStructureHasChanged( dataModel.getAttrs().getHeader() ) );
									    
							    		thematicMap.getCartographicDisplay().setJoinIdColumnName( MapUIHelper.DEFAULT_JOIN_ID_COLUMN_NAME );
							    		thematicMap.getCartographicDisplay().setDataColumnName( MapUIHelper.DEFAULT_DATA_COLUMN_NAME );		    		
							    		
							    		thematicMapUIHelper.applyThematicMap( thisFrame );								    
	
									} catch (TMapException e1) {
										miscUIHelper.displayErrorMessage( thisFrame, e1 );
									}
					            }
							}
						}
					});
		}
		return jMenuItemDataCreateAndPopulateWithJoinId;
	}

	private JMenuItem getJMenuItemDataEditStructure() {
		if (jMenuItemDataEditStructure == null) {
			jMenuItemDataEditStructure = new JMenuItem();
			jMenuItemDataEditStructure.setText("Edit Structure...");
			jMenuItemDataEditStructure.setMnemonic( 'u' );
			jMenuItemDataEditStructure
					.addActionListener(new ActionListener() {
						public void actionPerformed(ActionEvent e) {
							editDataStructure();
						}
					});
		}
		return jMenuItemDataEditStructure;
	}
	
	public void editDataStructure() {
    	DataTableDataModel dataModel =(DataTableDataModel)jFrameData.getJTable().getModel();
    	Attrs attrs =dataModel.getAttrs();
		JDialogEditDataStructure dlg =new JDialogEditDataStructure( null, attrs );
		dlg.setModal( true );
		dlg.setVisible( true );
		if ( dlg.isOkPressed() && dlg.isUpdated() ) {
	    	thematicMap.setDirty( true );
	    	// To refresh the data window
	    	dataModel.setAttrs( attrs );							

	    	//jFrameData.notifyObservers();
    		EventBus.publish( new DataStructureHasChanged( dataModel.getAttrs().getHeader() ) );
	    	
    		thematicMapUIHelper.applyThematicMap( thisFrame );
		}
		dlg.dispose();
	}

	private JMenuItem getJMenuItemCartographicDisplayEditNonMatchingInformation() {
		if (jMenuItemCartographicDisplayEditNonMatchingInformation == null) {
			jMenuItemCartographicDisplayEditNonMatchingInformation = new JMenuItem();
			jMenuItemCartographicDisplayEditNonMatchingInformation.setText("Edit Non Matching Information...");
			jMenuItemCartographicDisplayEditNonMatchingInformation
					.addActionListener(new ActionListener() {
						public void actionPerformed(ActionEvent e) {
							editCartographicDisplayNonMatchingInfo();
						}
					});
		}
		return jMenuItemCartographicDisplayEditNonMatchingInformation;
	}
	
	public void editCartographicDisplayNonMatchingInfo() {
		JDialogEditNonMatchingInfo dlg =new JDialogEditNonMatchingInfo(null, jFrameMap.getMappingToolKit());
		dlg.setModal( true );
		dlg.setVisible( true );
		if ( dlg.isOkPressed() && dlg.isUpdated() ) {
	    	thematicMap.setDirty( true );
	    	
	    	DataTableDataModel dataModel =(DataTableDataModel)jFrameData.getJTable().getModel();
	    	
	    	//jFrameData.notifyObservers();
	    		    	
    		EventBus.publish( new DataStructureHasChanged( dataModel.getAttrs().getHeader() ) );
	    	
    		thematicMapUIHelper.applyThematicMap( thisFrame );
		}
		dlg.dispose();	
	}

	public void setJFrameMain(JFrameMain frameMain) {
		jFrameMain = frameMain;
	}	
	

}
